/**
 * File: Scaffold2ContigProcessor.java
 * Created by: mhaimel
 * Created on: Jun 24, 2010
 * CVS:  $Id: Scaffold2ContigProcessor.java 1.0 Jun 24, 2010 11:32:21 AM mhaimel Exp $
 */
package uk.ac.ebi.curtain.utils.file;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import uk.ac.ebi.curtain.utils.CurtainUncheckedException;
import uk.ac.ebi.curtain.utils.io.impl.FileIO;

/**
 * @author mhaimel
 *
 */
public class Scaffold2ContigProcessor {
	private final AtomicInteger maxContigGap = new AtomicInteger(0);
	
	public Scaffold2ContigProcessor() {
		// do nothing
	}

	public static void processFiles(FileInfo input, FileInfo output){
		Scaffold2ContigProcessor processor = new Scaffold2ContigProcessor();
		processor.process(input,output);
	}
	
	private Pattern findNs = Pattern.compile("[^N]+");
	
	public void process(FileInfo input, FileInfo output) {
		final WriteUtil writer = output.getFileType().getWriter();
		final AtomicReference<PrintWriter> out = new AtomicReference<PrintWriter>();
		final int maxGap = getMaxContigGap();
//		if(maxGap > 0){
//			findNs = Pattern.compile("[^N]{"+maxGap+",}");
//		}
		try{
			out.set(new FileIO(output.getFile(),false).getPrintWriter());
			input.parse(new EntryMapper() {
				
				@Override
				public void mapEntry(EntryMapperBean bean) {
					String seq = bean.getSequence();
					if(seq.indexOf('n') >= 0 || seq.indexOf('N') >=0){
						splitBean(bean);
					} else {
						String id = bean.getId();
						id += ":0(0,"+seq.length()+")";
						bean.setId(id);
						submit(bean);
					}
				}
				
				private void splitBean(EntryMapperBean bean) {
					String seq = bean.getSequence().toUpperCase();
					Matcher m = findNs.matcher(seq);
					int i = 0;
					int start = -1;
					int end = 0;
					while(m.find()){
						int s = m.start();
						int e = m.end();
						String t1 = m.group();
						if(start == -1){
							start = s;
							end = e;
							continue;
						} else if((s-end) <= maxGap){
							end = e;
							continue;
						}
						String token = seq.substring(start, end);
						EntryMapperBean nBean = new EntryMapperBean(bean);
						nBean.setSequence(token);
						nBean.setSequenceLength(token.length());
						nBean.setId(bean.getId()+":"+i+"("+start+","+token.length()+")");
						submit(nBean);
						++i;
						start = s;
						end = e;
					}
					String token = seq.substring(start, end);
					EntryMapperBean nBean = new EntryMapperBean(bean);
					nBean.setSequence(token);
					nBean.setSequenceLength(token.length());
					nBean.setId(bean.getId()+":"+i+"("+start+","+token.length()+")");
					submit(nBean);					
				}
				private void submit(EntryMapperBean bean){
					writer.write(out.get(), bean);
				}
			});
		} catch (IOException e) {
			throw new CurtainUncheckedException("Problems writing to file " + output,e);
		} finally{
			FileIO.closeQuietly(out.getAndSet(null));
		}
	}

	public void setMaxContigGap(Integer maxContigGap) {
		this.maxContigGap.set(maxContigGap);
	}
	public int getMaxContigGap() {
		return maxContigGap.get();
	}
}
